package edu.gdpu.jmm;

/**
 * @author mazebin
 * @date 2021年 07月15日 22:39:17
 * MESI:CPU缓存一致性协议
 * https://www.cnblogs.com/z00377750/p/9180644.html
 * 一个缓存行为64bit
MESI协议中的状态#
CPU中每个缓存行（caceh line)使用4种状态进行标记（使用额外的两位(bit)表示):

M: 被修改（Modified)

该缓存行只被缓存在该CPU的缓存中，并且是被修改过的（dirty),即与主存中的数据不一致，该缓存行中的内存需要在未来的某个时间点（允许其它CPU读取请主存中相应内存之前）写回（write back）主存。

当被写回主存之后，该缓存行的状态会变成独享（exclusive)状态。

E: 独享的（Exclusive)

该缓存行只被缓存在该CPU的缓存中，它是未被修改过的（clean)，与主存中数据一致。该状态可以在任何时刻当有其它CPU读取该内存时变成共享状态（shared)。

同样地，当CPU修改该缓存行中内容时，该状态可以变成Modified状态。

S: 共享的（Shared)

该状态意味着该缓存行可能被多个CPU缓存，并且各个缓存中的数据与主存数据一致（clean)，当有一个CPU修改该缓存行中，其它CPU中该缓存行可以被作废（变成无效状态（Invalid））。

I: 无效的（Invalid）

该缓存是无效的（可能有其它CPU修改了该缓存行）。
 */
public class MESICacheLinePaddingTest1 {
    private static  final  int count = 1000_0000;
    private static class T{
        public volatile  long x=0L;
    }
    private static T[] arr = new T[2];
    //arr[0]和arr[1]在同一个缓存行中概率非常大
    static {
        arr[0] = new T();
        arr[1] = new T();

    }

    public static void main(String[] args) throws Exception {
        test();
    }
    //使用两个线程去分别修改arr[0]和arr[1]中的值
    public  static void test() throws Exception{
     Thread t1 = new Thread(()->{
         for(long i =0; i<count;i++) {
             arr[0].x = i;
         }
        });

        Thread t2 = new Thread(()->{
            for (long i = 0; i < count; i++) {
                arr[1].x = i;
            }
        });

        final long start = System.nanoTime();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println((System.nanoTime() - start)/100_0000);//275

    }
}
